package edu.stanford.prpl.dynUI;

import java.net.*;
import java.io.*;
import java.util.HashMap;
import java.util.Map;

import org.kxml2.io.KXmlParser;
import org.xmlpull.v1.*;

import edu.stanford.prpl.dynUI.templates.*;


// Input: Template file, XML data
// Output: UI Code for Web & Android Platforms
// For Android: Click on items should launch Activity, create View objects for the UI

// UIEngine is only stateful for the template,
// stateless for the input data

public class UIEngine 
{
    public enum devicePlatform 
    { WEB, ANDROID, IPHONE }
    
    public devicePlatform selectedPlatform = devicePlatform.WEB;
    
	// UI Template data structures
	Map<String,UITemplate> uiPages 
	= new HashMap<String,UITemplate>();
	
	// Only one active UI Page at a time
	// private Object currentUIPage = null;


	public UIEngine(devicePlatform dP) throws Exception
	{
		this.selectedPlatform = dP;
	}


	public void setTemplate(Reader templateFileReader) throws Exception
	{
        // XmlPullParserFactory factory;
        XmlPullParser template_xpp;

        try
        {
        	XmlPullParserFactory factory = XmlPullParserFactory.newInstance("org.kxml2.io.KXmlParser", KXmlParser.class);
        	// factory.setNamespaceAware(true);
        	
        	template_xpp = factory.newPullParser(); // new KXmlParser();
            // template_xpp.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
            template_xpp.setInput ( templateFileReader );
        }
        catch(Exception e)
        {
            // Error
            System.out.println("Processing Template Exception e: " + e.toString());
            throw e;
            // return;
        }
   
        // System.out.println("Starting the Processing of the UI template...");
	    processTemplate(template_xpp);
	    // System.out.println("Ending the Processing of the UI template...");
	}
	
	private void processTemplate(XmlPullParser xpp) throws Exception
	{
        try
        {       
            int eventType = xpp.getEventType();
            do 
            {
                if (eventType == XmlPullParser.START_DOCUMENT) 
                {
                    System.out.println("Start of template document");
                } 
                else if(eventType == XmlPullParser.END_DOCUMENT)
                {
                    System.out.println("End of template document");
                } 
                else if(eventType == XmlPullParser.START_TAG) 
                {
                    processTemplateStartElement(xpp);
                }
                else if(eventType == XmlPullParser.END_TAG) 
                {
                    processEndElement(xpp);
                }
                else if(eventType == XmlPullParser.TEXT) 
                {
                    processText(xpp);
                }
                eventType = xpp.next();
            } 
            while (eventType != XmlPullParser.END_DOCUMENT);
        }
        catch(Exception e)
        {
            // Error
            System.out.println("Exception e: " + e.toString());
            throw e;
            // return;
        }
        
	}
		
    private void processTemplateStartElement (XmlPullParser xpp)
    {
        String name = xpp.getName();
        String uri = xpp.getNamespace();

        if ("".equals (uri)) {
            System.out.println("Start element: " + name);
        } else {
            System.out.println("Start element: {" + uri + "}" + name);
        }        

        if (name.equals("dynUI:listPage"))
        {
           UITemplate naviListObj = new DynNaviListPageUITemplate(this.selectedPlatform);

           System.out.println("Processing for Dynamic Navigation List UI...");
           try
           {
        	   naviListObj.parseTemplate(xpp);
        	   if (naviListObj.dataObjectName == null)
        	      uiPages.put("*", naviListObj);
        	   else
        	      uiPages.put(naviListObj.dataObjectName, naviListObj);
           }
           catch (Exception e)
           {
        	   System.out.println("\t processTemplate Exception: " + e.toString());
           }     
        }
        else if (name.equals("dynUI:multiUIPage"))
        {
        	System.out.println("Processing for Multi UI-Elements Page not implemented yet...");
        }       

    }

    private void processEndElement (XmlPullParser xpp)
    {
        String name = xpp.getName();
        String uri = xpp.getNamespace();
        if ("".equals (uri))
            System.out.println("End element: " + name);
        else
            System.out.println("End element:   {" + uri + "}" + name);
    }


    int holderForStartAndLength[] = new int[2];

    private void processText (XmlPullParser xpp) throws XmlPullParserException
    {
        char ch[] = xpp.getTextCharacters(holderForStartAndLength);
        int start = holderForStartAndLength[0];
        int length = holderForStartAndLength[1];
        System.out.print("Characters:    \"");
        for (int i = start; i < start + length; i++) {
            switch (ch[i]) {
                case '\\':
                    System.out.print("\\\\");
                    break;
                case '"':
                    System.out.print("\\\"");
                    break;
                case '\n':
                    System.out.print("\\n");
                    break;
                case '\r':
                    System.out.print("\\r");
                    break;
                case '\t':
                    System.out.print("\\t");
                    break;
                default:
                    System.out.print(ch[i]);
                    break;
            }
        }
        System.out.print("\"\n");
    }



    public enum renderType 
    { NORMAL, AJAX_WEB_FRAGMENT }

    // public android.view.View renderAndroidUI(String dataFileLoc) throws Exception
	public Object render(Reader dataFileReader, String pageTitle, renderType uiRendering) throws Exception
	{
        XmlPullParser data_xpp;

        try
        {
        	XmlPullParserFactory factory = XmlPullParserFactory.newInstance("org.kxml2.io.KXmlParser", KXmlParser.class);
        	// factory.setNamespaceAware(false);
        	
        	data_xpp = factory.newPullParser(); // new KXmlParser();
            // data_xpp.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
            data_xpp.setInput ( dataFileReader );
        }
        catch(Exception e)
        {
            // Error
            System.out.println("Exception e: " + e.toString());
            throw e;
            // return;
        }

        UIModelData uiData = new UIModelData();
        this.processData(data_xpp, uiData);
        if (pageTitle != null)
           uiData.attributesStore.put("_PageTitle", pageTitle);
        
        if (uiData.uiTemplate != null) {
            if (uiRendering == renderType.NORMAL)
                uiData.uiTemplate.generateUI(uiData);
            else if (uiRendering == renderType.AJAX_WEB_FRAGMENT)
                uiData.uiTemplate.generateUIFragment(uiData);
        }
            
        return uiData.uiObject;
	}
	
    private void processData(XmlPullParser xpp, UIModelData uiData) throws Exception
    {
        try
        {
            int eventType = xpp.getEventType();
            do 
            {
                if (eventType == XmlPullParser.START_DOCUMENT) 
                {
                    System.out.println("Start of data document");
                } 
                else if(eventType == XmlPullParser.END_DOCUMENT)
                {
                    System.out.println("End of data document");
                } 
                else if(eventType == XmlPullParser.START_TAG) 
                {
                    processDataStartElement(xpp, uiData);
                }
                else if(eventType == XmlPullParser.END_TAG) 
                {
                    processEndElement(xpp);
                }
                else if(eventType == XmlPullParser.TEXT) 
                {
                    processText(xpp);
                }
                eventType = xpp.next();
            } 
            while (eventType != XmlPullParser.END_DOCUMENT);
        }
        catch(Exception e)
        {
            // Error
            System.out.println("Exception e: " + e.toString());
            throw e;
            // return;
        }

    }

    private void processDataStartElement (XmlPullParser xpp, UIModelData uiData)
    {
        String name = xpp.getName();
        String uri = xpp.getNamespace();

        if ("".equals (uri)) {
            System.out.println("Start element: " + name);
        } else {
            System.out.println("Start element: {" + uri + "}" + name);
        }

        UITemplate uiContext = uiPages.get(name);
        if (uiContext != null)
        {
            try
            {
               System.out.println("\nProcessing UI for data element: " + name);
               
               // Set the current UI page to be displayed
               uiData.uiTemplate = uiContext;
               uiContext.parseData(xpp, uiData);
               
               // System.out.println("\nDEBUG");
               // At this point, after returning from parseData(),
               // xml parser should be at the closing tag of current element
            }
            catch (Exception e)
            {
                System.out.println("\t processData Exception: " + e.toString());
            } 
        }
    }	
	

	// comboPage, hybridPage, mashupPage
	// android.view.View
    

	/**
	 * @param args
	 * @throws Exception 
	 */
    /*
	public static void main(String[] args) throws Exception 
	{
		System.out.println("Starting lightweight UI Template package...");
		UIEngine webUI_engine = new UIEngine(UIEngine.devicePlatform.WEB);
		
		webUI_engine.setTemplate(new BufferedReader(new FileReader("DynNaviList.template.xml")));

		
        URL jinzoraData_xml = new URL("http://prpl.stanford.edu/music/api.php?user=skteh&pass=serangga&request=browse&jz_path=%2F");
        BufferedReader in = new BufferedReader(
                                new InputStreamReader(jinzoraData_xml.openStream())
                            );
		Object UIresult = webUI_engine.render(in, "Genre", renderType.AJAX_WEB_FRAGMENT);
		

		// Object UIresult = webUI_engine.render(new BufferedReader(new FileReader("jinzora_data.xml")), "Jinzora", renderType.NORMAL);
		// Object UIresult = webUI_engine.render(new BufferedReader(new FileReader("jinzora_data.xml")), "Jinzora", renderType.AJAX_WEB_FRAGMENT);
		if (UIresult instanceof String)
		    System.out.println("\n\nHTML Output: \n" + ((String)UIresult) + "\n\n");
		if (UIresult == null)
            System.out.println("\n\nUI Result is NULL! \n");

		System.out.println("DONE!");
	}
    */



}
